package com.pig.sentinel.context;

import com.pig.sentinel.SentinalConst;

import java.lang.reflect.Method;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author lizhiwei
 */
public class FlowContext {
    public static final long ONE_SECOND_MS = 1000L;
    public static final long MAX_SIZE = ONE_SECOND_MS / SentinalConst.QPS_COMPUTE_INTERVAL;
    /**
     * 10ms内第有一次请求，此值+1
     */
    private AtomicLong tenMsQps = new AtomicLong(0);
    /**
     * 堆积的任务
     */
    private BlockingQueue<Method> taskQueue = new ArrayBlockingQueue<>(SentinalConst.FLOW_QUEUE_MAX_SIZE);
    /**
     * 存放最近1000ms中每10ms内的qps
     */
    private BlockingQueue<Long> qpsQueue = new LinkedBlockingQueue<>((int) MAX_SIZE);

    /**
     * 得到当前的qps
     *
     * @return
     */
    public long getCurrentQpc() {
        return qpsQueue.parallelStream().reduce((v1, v2) -> v1 + v2).orElse(0L);
    }

    public void incExeTimes() {
        tenMsQps.incrementAndGet();
    }

    /**
     * 每10ms计算一下qps
     */
    public void addQpsQueue() {
        while (!qpsQueue.offer(tenMsQps.get())) {
            qpsQueue.poll();
        }
        tenMsQps.set(0);
    }
}
